﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace game
{
    public class FlyDownMovement2
    {
        public float RollSpeed { get; set; }
        public float FallSpeed { get; set; }
        public float LeanStablePointEpsilon { get; set; }

        public float OldLayerHeight { get; private set; }
        public float NewLayerHeight { get; private set; }

        private float distY;
        private float movedY;

        private float snapToLayerOffset = 20.0f;

        private bool falling;
        private float rollStopPoint = 1.0f; // radians

        public bool Finished { get; private set; }

        private enum State
        {
            BEGIN_ROLL,
            FALL,
            MID_ROLL,
            END_ROLL,
        }

        private State state;

        public FlyDownMovement2()
        {
            RollSpeed = 0.003f;
            FallSpeed = 22.0f;
            LeanStablePointEpsilon = 0.1f;
        }

        public void Start(float oldLayerHeight, float newLayerHeight)
        {
            this.OldLayerHeight = oldLayerHeight;
            this.NewLayerHeight = newLayerHeight;
            Finished = false;
            falling = true;
            state = State.BEGIN_ROLL;
            distY = oldLayerHeight - newLayerHeight;
            movedY = 0;
        }

        
        

        public void RotateZAndFall(ref float curRot, ref Vector3 curPos)
        {
            float fallMove = 0.0f;
            switch (state)
            {
                case State.BEGIN_ROLL:
                    curRot += 0.8f * RollSpeed * MovementControl.DeltaTimeMs;
                    if (curRot > rollStopPoint)
                    {
                        state = State.FALL;
                    }
                    fallMove = curRot * curRot * FallSpeed * MovementControl.DeltaTimeMs;
                    
                    break;

                case State.FALL:
                    fallMove = rollStopPoint * rollStopPoint * FallSpeed * MovementControl.DeltaTimeMs;
                    if (movedY > distY * 0.40f)
                    {
                        state = State.MID_ROLL;
                    }
                    break;

                case State.MID_ROLL:
                    curRot += 2.0f * RollSpeed * MovementControl.DeltaTimeMs;
                    if (curRot > MathHelper.Pi)
                    {
                        curRot -= MathHelper.TwoPi;
                    }
                    if (curRot < 0 && curRot > -rollStopPoint)
                    {
                        state = State.END_ROLL;
                    }
                    fallMove = rollStopPoint * rollStopPoint * FallSpeed * MovementControl.DeltaTimeMs;
                    break;

                case State.END_ROLL:
                    if (Math.Abs(curRot) < LeanStablePointEpsilon)
                    {
                        curRot = 0.0f;
                        fallMove = 10.0f;

                        if(!falling)
                            Finished = true;
                    }
                    else
                    {
                        curRot += RollSpeed * MovementControl.DeltaTimeMs;
                        if (falling)
                        {
                            fallMove = curRot * curRot * FallSpeed * MovementControl.DeltaTimeMs;
                        }
                    }

                    if ((distY - movedY) < snapToLayerOffset && falling)
                    {
                        curPos.Y = NewLayerHeight;
                        fallMove = 0.0f;
                        falling = false;

                        if(curRot == 0.0f)
                            Finished = true;
                    }
                    break;
            }

            curPos.Y -= fallMove;
            movedY += fallMove;
        }
    }
}
